/**
 * 
 */
package mx.com.asteca.vista;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.ViewScoped;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.model.SelectItem;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import mx.com.asteca.comun.Constantes;
import mx.com.asteca.comun.dto.AlumnoDTO;
import mx.com.asteca.comun.dto.CursoDTO;
import mx.com.asteca.comun.dto.EmisionCertificadoDTO;
import mx.com.asteca.comun.dto.MateriaCalificacionDTO;
import mx.com.asteca.comun.dto.MateriaDTO;
import mx.com.asteca.comun.dto.PermisosBooleanDTO;
import mx.com.asteca.comun.dto.ProgramaEstudiosDTO;
import mx.com.asteca.fachada.EmisionCertificadoFachada;
import mx.com.asteca.fachada.FachadaException;
import mx.com.asteca.util.RandomString;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperCompileManager;
import net.sf.jasperreports.engine.JasperExportManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.io.FileUtils;
import org.primefaces.context.RequestContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author JAMARO
 * 
 */
@ManagedBean(name = Constantes.BEAN_EMISION_CERTIFICADOS)
@ViewScoped
public class EmisionCertificadoControlador extends BaseController {

	private static final Logger LOGGER = LoggerFactory
			.getLogger(EmisionCertificadoControlador.class);

	private static final String modulo = Constantes.MODULO_EMISION_CERTIFICADOS;
	private PermisosBooleanDTO permisos;
	@ManagedProperty("#{emisionCertificadoFachadaImpl}")
	private EmisionCertificadoFachada fachada;

	private List<CursoDTO> listCursos;
	private List<SelectItem> listSelectCursos;
	private List<AlumnoDTO> listAlumnos;
	private Integer idCursoSelected;
	private boolean displayPanel1 = false;
	private List<AlumnoDTO> selectedAlumnos;
	private String leyenda1;
	private String leyenda2;
	private String folio;
	private String pdfPath;
	private boolean mostrarPanelReporte;

	private void initListCursos() {
		try {
			if (CollectionUtils.isEmpty(listCursos)) {
				listCursos = fachada.findAllCursos();
			}
		} catch (FachadaException e) {
			super.addErrorMessage(Constantes.MESSAGE_TITLE_ERROR,
					Constantes.ERROR_OBTENIENDO_LISTA_CATALOGO);
		}
	}

	private void initListSelectCursos() {
		if (CollectionUtils.isEmpty(listSelectCursos)) {
			listSelectCursos = new ArrayList<SelectItem>();
			for (CursoDTO dto : getListCursos()) {
				SelectItem item = new SelectItem(dto.getIdCurso(),
						dto.getReferencia());
				listSelectCursos.add(item);
			}
		}
	}

	@PostConstruct
	public void populate() {
		setPermisos(super.stablishSessionPermissions());
	}

	public void buscaAlumnos() {
		if (idCursoSelected == null || idCursoSelected == 0) {
			super.addWarningMessage(Constantes.MESSAGE_TITLE_WARNING,
					Constantes.WARNING_SELECCIONAR_UN_REGISTRO);
			displayPanel1 = false;
			return;
		}
		try {
			CursoDTO dtoCurso = fachada.findByPK(idCursoSelected);
			listAlumnos = fachada.findAlumnosPorCurso(dtoCurso);
			displayPanel1 = true;
			super.addInfoMessage("Selecciona los alumnos para emitir certificado y llena campos requeridos");
		} catch (FachadaException e) {
			super.addErrorMessage(Constantes.MESSAGE_TITLE_ERROR,
					Constantes.ERROR_OBTENIENDO_LISTA_CATALOGO);
		}
	}

	public void emiteCertificados() {
		try {
			if (CollectionUtils.isEmpty(selectedAlumnos)) {
				super.addWarningMessage(Constantes.MESSAGE_TITLE_WARNING,
						Constantes.WARNING_SELECCIONAR_UN_REGISTRO);
				return;
			}
			List<EmisionCertificadoDTO> listCertificados = new ArrayList<EmisionCertificadoDTO>();
			for (AlumnoDTO alumnoDTO : selectedAlumnos) {
				EmisionCertificadoDTO certificado = new EmisionCertificadoDTO();
				certificado.setDtoAlumno(alumnoDTO);
				CursoDTO dtoCurso = fachada.findByPK(idCursoSelected);
				ProgramaEstudiosDTO dtoProgrEstudios = fachada
						.findProgramaEstudiosPorCurso(dtoCurso);
				certificado.setDtoProgrEstudios(dtoProgrEstudios);
				certificado.setDtoCurso(dtoCurso);
				certificado.setLeyenda1(leyenda1);
				certificado.setLeyenda2(leyenda2);
				Map<MateriaDTO, String> mapMateriasCalificaciones = fachada
						.findMateriasCalificaciones(dtoCurso, alumnoDTO);
				List<MateriaCalificacionDTO> listaMateriasCalificaciones = new ArrayList<MateriaCalificacionDTO>();
				String promedio = "", resultado = "";
				double promedio_ = 0, resultado_ = 0;
				int contador = 0;
				for (MateriaDTO mat : mapMateriasCalificaciones.keySet()) {
					MateriaCalificacionDTO dto = new MateriaCalificacionDTO();
					dto.setMateriaNombre(mat.getNombre());
					String c = mapMateriasCalificaciones.get(mat);
					dto.setMateriaCalificacion(c);
					contador++;
					promedio_ += Double.parseDouble(c);
					listaMateriasCalificaciones.add(dto);
				}
				promedio_ = promedio_ / contador;
				resultado = "S";
				promedio = String.valueOf(promedio_);
				certificado.setPromedio(promedio);
				certificado.setResultado(resultado);
				certificado
						.setListMateriasCalificaciones(listaMateriasCalificaciones);
				listCertificados.add(certificado);
			}

			try {
				InputStream ins = FacesContext
						.getCurrentInstance()
						.getExternalContext()
						.getResourceAsStream(
								"/WEB-INF/JASPER/certificado" + ".jrxml");
				JasperReport report = JasperCompileManager.compileReport(ins);
				JRBeanCollectionDataSource ds = new JRBeanCollectionDataSource(
						listCertificados);
				Map<String, Object> param = new HashMap<String, Object>();
				/**
				 * Passing ReportTitle and Author as parameters
				 */
				param.put("paramFolio", folio);
				param.put("paramLeyenda1", leyenda1);
				param.put("paramLeyenda2", leyenda2);
				InputStream inss = FacesContext.getCurrentInstance()
						.getExternalContext()
						.getResourceAsStream("/WEB-INF/JASPER/logo_asteca.png");
				HttpServletRequest servletReq = (HttpServletRequest) FacesContext
						.getCurrentInstance().getExternalContext().getRequest();
				String request = servletReq.getRequestURL().toString();
				int index = request.lastIndexOf("faces");
				String reqlReq = request.substring(0, index);
				reqlReq += "resources/images/logo_asteca.png";
				param.put("imagenLogo", reqlReq);

				JasperPrint print = JasperFillManager.fillReport(report, param,
						ds);
				String realPath2 = FacesContext.getCurrentInstance().getExternalContext().getRealPath("tmp");
				String path2 =  "/"+RandomString.getRandomString()+"_certificado_"+".pdf";
				String path = realPath2 + path2;
				File pdfTemp = new File(path);
				byte[] file = JasperExportManager.exportReportToPdf(print);
				FileUtils.writeByteArrayToFile(pdfTemp, file);
				pdfPath = "/tmp"+ path2;
				mostrarPanelReporte = true;
			} catch (JRException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
		} catch (FachadaException e) {
			super.addErrorMessage(Constantes.MESSAGE_TITLE_ERROR,
					Constantes.ERROR_OBTENIENDO_LISTA_CATALOGO);
		}
	}
	
	public void descargarCertificado(){
		try {
			if (CollectionUtils.isEmpty(selectedAlumnos)) {
				super.addWarningMessage(Constantes.MESSAGE_TITLE_WARNING,
						Constantes.WARNING_SELECCIONAR_UN_REGISTRO);
				return;
			}
			List<EmisionCertificadoDTO> listCertificados = new ArrayList<EmisionCertificadoDTO>();
			for (AlumnoDTO alumnoDTO : selectedAlumnos) {
				EmisionCertificadoDTO certificado = new EmisionCertificadoDTO();
				certificado.setDtoAlumno(alumnoDTO);
				CursoDTO dtoCurso = fachada.findByPK(idCursoSelected);
				ProgramaEstudiosDTO dtoProgrEstudios = fachada
						.findProgramaEstudiosPorCurso(dtoCurso);
				certificado.setDtoProgrEstudios(dtoProgrEstudios);
				certificado.setDtoCurso(dtoCurso);
				certificado.setLeyenda1(leyenda1);
				certificado.setLeyenda2(leyenda2);
				Map<MateriaDTO, String> mapMateriasCalificaciones = fachada
						.findMateriasCalificaciones(dtoCurso, alumnoDTO);
				List<MateriaCalificacionDTO> listaMateriasCalificaciones = new ArrayList<MateriaCalificacionDTO>();
				String promedio = "", resultado = "";
				double promedio_ = 0, resultado_ = 0;
				int contador = 0;
				for (MateriaDTO mat : mapMateriasCalificaciones.keySet()) {
					MateriaCalificacionDTO dto = new MateriaCalificacionDTO();
					dto.setMateriaNombre(mat.getNombre());
					String c = mapMateriasCalificaciones.get(mat);
					dto.setMateriaCalificacion(c);
					contador++;
					promedio_ += Double.parseDouble(c);
					listaMateriasCalificaciones.add(dto);
				}
				promedio_ = promedio_ / contador;
				resultado = "S";
				promedio = String.valueOf(promedio_);
				certificado.setPromedio(promedio);
				certificado.setResultado(resultado);
				certificado
						.setListMateriasCalificaciones(listaMateriasCalificaciones);
				listCertificados.add(certificado);
			}
			HttpServletRequest req = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
			HttpSession session = req.getSession();
			String request = req.getRequestURL().toString();
			int index = request.lastIndexOf("faces");
			String reqlReq = request.substring(0, index);
			String url = reqlReq;
			reqlReq += "resources/images/logo_asteca.png";
			session.setAttribute("paramFolio", folio);
			session.setAttribute("listCertificados", listCertificados);
			session.setAttribute("leyenda1", leyenda1);
			session.setAttribute("leyenda2", leyenda2);
			session.setAttribute("logoAsteca", reqlReq);
			RequestContext.getCurrentInstance().execute("window.open('" + url + "EmiteCertificado"
					+ "')");
		} catch (FachadaException e) {
			super.addErrorMessage(Constantes.MESSAGE_TITLE_ERROR,
					Constantes.ERROR_OBTENIENDO_LISTA_CATALOGO);
		}
	}
	
	
	/**
	 * @return the permisos
	 */
	public PermisosBooleanDTO getPermisos() {
		return permisos;
	}

	/**
	 * @param permisos
	 *            the permisos to set
	 */
	public void setPermisos(PermisosBooleanDTO permisos) {
		this.permisos = permisos;
		super.setAlta(permisos.isAlta());
		super.setBorrar(permisos.isBorrar());
		super.setCambios(permisos.isEdicion());
		super.setConsulta(permisos.isConsulta());
		super.setImpresion(permisos.isImpresion());
	}

	@Override
	String getModulo() {
		return modulo;
	}

	/**
	 * @return the fachada
	 */
	public EmisionCertificadoFachada getFachada() {
		return fachada;
	}

	/**
	 * @param fachada
	 *            the fachada to set
	 */
	public void setFachada(EmisionCertificadoFachada fachada) {
		this.fachada = fachada;
	}

	/**
	 * @return the listCursos
	 */
	public List<CursoDTO> getListCursos() {
		initListCursos();
		return listCursos;
	}

	/**
	 * @param listCursos
	 *            the listCursos to set
	 */
	public void setListCursos(List<CursoDTO> listCursos) {
		this.listCursos = listCursos;
	}

	/**
	 * @return the listSelectCursos
	 */
	public List<SelectItem> getListSelectCursos() {
		initListSelectCursos();
		return listSelectCursos;
	}

	/**
	 * @param listSelectCursos
	 *            the listSelectCursos to set
	 */
	public void setListSelectCursos(List<SelectItem> listSelectCursos) {
		this.listSelectCursos = listSelectCursos;
	}

	/**
	 * @return the listAlumnos
	 */
	public List<AlumnoDTO> getListAlumnos() {
		return listAlumnos;
	}

	/**
	 * @param listAlumnos
	 *            the listAlumnos to set
	 */
	public void setListAlumnos(List<AlumnoDTO> listAlumnos) {
		this.listAlumnos = listAlumnos;
	}

	/**
	 * @return the idCursoSelected
	 */
	public Integer getIdCursoSelected() {
		return idCursoSelected;
	}

	/**
	 * @param idCursoSelected
	 *            the idCursoSelected to set
	 */
	public void setIdCursoSelected(Integer idCursoSelected) {
		this.idCursoSelected = idCursoSelected;
	}

	/**
	 * @return the displayPanel1
	 */
	public boolean isDisplayPanel1() {
		return displayPanel1;
	}

	/**
	 * @param displayPanel1
	 *            the displayPanel1 to set
	 */
	public void setDisplayPanel1(boolean displayPanel1) {
		this.displayPanel1 = displayPanel1;
	}

	/**
	 * @return the selectedAlumnos
	 */
	public List<AlumnoDTO> getSelectedAlumnos() {
		return selectedAlumnos;
	}

	/**
	 * @param selectedAlumnos
	 *            the selectedAlumnos to set
	 */
	public void setSelectedAlumnos(List<AlumnoDTO> selectedAlumnos) {
		this.selectedAlumnos = selectedAlumnos;
	}

	/**
	 * @return the leyenda1
	 */
	public String getLeyenda1() {
		return leyenda1;
	}

	/**
	 * @param leyenda1
	 *            the leyenda1 to set
	 */
	public void setLeyenda1(String leyenda1) {
		this.leyenda1 = leyenda1;
	}

	/**
	 * @return the leyenda2
	 */
	public String getLeyenda2() {
		return leyenda2;
	}

	/**
	 * @param leyenda2
	 *            the leyenda2 to set
	 */
	public void setLeyenda2(String leyenda2) {
		this.leyenda2 = leyenda2;
	}

	/**
	 * @return the folio
	 */
	public String getFolio() {
		return folio;
	}

	/**
	 * @param folio
	 *            the folio to set
	 */
	public void setFolio(String folio) {
		this.folio = folio;
	}

	/**
	 * @return the pdfPath
	 */
	public String getPdfPath() {
		return pdfPath;
	}

	/**
	 * @param pdfPath the pdfPath to set
	 */
	public void setPdfPath(String pdfPath) {
		this.pdfPath = pdfPath;
	}

	/**
	 * @return the mostrarPanelReporte
	 */
	public boolean isMostrarPanelReporte() {
		return mostrarPanelReporte;
	}

	/**
	 * @param mostrarPanelReporte the mostrarPanelReporte to set
	 */
	public void setMostrarPanelReporte(boolean mostrarPanelReporte) {
		this.mostrarPanelReporte = mostrarPanelReporte;
	}

}
